// 字符串的一些面试题

#include <string.h>
#include <assert.h>
#include <stdio.h>

char* strcpy(char* pDest, const char* pSrc)
{
    //要判断空
    if(pDest==NULL || pSrc==NULL)
        throw "Null Argument!";
    //注意记录
    char* pDestCpy = pDest;
    while((*pDestCpy++ = *pSrc++)!='\0')
        ;
    return pDest;
}

char* strcpy1(char* pDest, const char* pSrc)
{
    assert(pDest != NULL);  
    assert(pSrc != NULL);  
    char *ret = pDest;  
    memcpy(pDest,pSrc,strlen(pSrc)+1);  
    return pDest;
}   

char* strncpy(char* pDest, const char* pSrc, int size)
{
    assert(pDest!=NULL && pSrc!=NULL);
    assert(size>=0);
    char* pDestCpy = pDest;
    while(size-- && (*pDestCpy++ = *pSrc++)!='\0') 
        ;
    if(size>0)
        while(size--)
            *pDestCpy++='\0';
    return pDest;
}  

char* strcat(char* pDest, const char* pSrc)
{
    assert(pDest != NULL && pSrc!=NULL);
    char* pDestCpy = pDest + strlen(pDest);
    while((*pDestCpy++ = *pSrc++)!='\0') ;
    return pDest;    
}

char* strncat(char* pDest, char* pSrc, int size)
{
    assert(pDest!=NULL && pSrc!=NULL);
    assert(size>=0);
    char* pDestCpy = pDest + strlen(pDest);
    while(size-- && (*pDestCpy++ = *pSrc++)!='\0');
    return pDest;
} 

void* memset(void* pDest, int value, int size)
{
    assert(pDest!=NULL && size>=0);
    char* pDestCpy = (char*)pDest;
    while(size--)
        *pDestCpy++ = value;
    return pDest;
}

void* memcpy(void* pDest, const void* pSrc, int size)
{
    assert(pDest!=NULL && pSrc!=NULL && size>=0);
    char* pDestCpy = NULL;
    char* pSrcCpy = NULL;
    //要复制的内存有重叠时,从后往前复制
    if(pSrc<pDest && (char*)pSrc+size>(char*)pDest)
    {
        pDestCpy = (char*)pDest+size-1;
        pSrcCpy = (char*)pSrc+size-1;
        while(size--)
            *pDestCpy-- = *pSrcCpy--;
    }
    else
    {
        pDestCpy = (char*)pDest;
        pSrcCpy = (char*)pSrc;
        while(size--)
            *pDestCpy++ = *pSrcCpy++;
    }
    return pDest;
}  

void* memmove(void* dest, const void* src, int size)
{
    assert(dest!=NULL && src!=NULL && size>=0);
    char* pDest = (char*)dest;
    char* pSrc = (char*)src;
    //复制内容重叠时，从后往前复制
    if(pSrc<pDest && pSrc+size>pDest)
    {
        pDest+=size-1;
        pSrc+=size-1;
        while(size--)
            *pDest-- = *pSrc--;
    }
    else
    {
        while(size--)
            *pDest++ = *pSrc++;
    }
    return dest;
}

// // dst地址若在C区间，则正向复制会有内存重叠
// // 故C区间必须反向复制
// // |  _______________________________________
// // |      A  |    B     |    C      |  D
// // |  _______|__________|___________|________
// // |                   src
// // |         |-src_size-|-src_size--|
// char* strcpy(char* dst, const char* src)
// {
//     assert(dst && src);
//     char* ret = dst;
//     size_t src_size = strlen(src);

//     if (dst > src && dst <= src+src_size) { // 反向复制，C区间左开右闭
//         src = src + src_size;               // 定位到源字符串的'\0'
//         dst = dst + src_size;               // 定位目的字符串的'\0'
//         int loop = src_size + 1;            // 循环strlen(src)+1次,因为要包括'\0'
//         while (loop--)
//             *dst-- = *src--;
//         //return dst+1;                     // 赋值需要strlen(src)+1次，而递减只需要strlen(src)次,多减了一次，所以返回dst+1
//     } else {                                // 正向复制
//         while ((*dst++=*src++) != '\0');
//     }

//     return ret;
// }



int main() {
    const char str[20] = "0123456789\0";
    const char* src;//strlen(src) == 5 src == "56789\0"

    char* dst;
    char *p;

    // //dst在C区间右边界
    // src = str + 5;
    // dst = str + 10;    
    // p  = strcopy(dst, src);
    // printf("%s\n", p);

    // //dst在C区间左边界
    // src = str + 5;
    // dst = str + 5;
    // p = strcopy(dst, src);
    // printf("%s\n", p);

    // //dst在C区间
    // dst = str +8;
    // src = str + 5;
    // p = strcopy(dst, src);
    // printf("%s\n", p);

    //dst在ABD区间
    src = str + 5;
    char str1[20];
    dst = str1;
    p = strcopy(dst, src);
    printf("%s\n", p);
}